#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <stdint.h>
#include <assert.h>
#include <pthread.h>
#include "cJSON.h"
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "uart.h"



/* global variable ---------------------------------------------------------*/
int uart_fd;



/**
  * @brief  
  * param
  * @retval None
  */
uint8_t NMEA_Comma_Pos(uint8_t *buf,uint8_t cx)
{	 		    
	uint8_t *p=buf;
	while(cx)
	{		 
		if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号
		if(*buf==',')cx--;
		buf++;
	}
	return buf-p;	 
}
	
/**
  * @brief  
  * param
  * @retval None
  */
uint32_t NMEA_Pow(uint8_t m,uint8_t n)
{
	uint32_t result=1;	 
	while(n--)result*=m;    
	return result;
}
/**
  * @brief  
  * param
  * @retval None
  */
int NMEA_Str2num(uint8_t *buf,uint8_t*dx)
{
	uint8_t *p=buf;
	uint32_t ires=0,fres=0;
	uint8_t ilen=0,flen=0,i;
	uint8_t mask=0;
	int res;
	while(1) //得到整数和小数的长度
	{
		if(*p=='-'){mask|=0X02;p++;}//是负数
		if(*p==','||(*p=='*'))break;//遇到结束了
		if(*p=='.'){mask|=0X01;p++;}//遇到小数点了
		else if(*p>'9'||(*p<'0'))	//有非法字符
		{	
			ilen=0;
			flen=0;
			break;
		}	
		if(mask&0X01)flen++;
		else ilen++;
		p++;
	}
	if(mask&0X02)buf++;	//去掉负号
	for(i=0;i<ilen;i++)	//得到整数部分数据
	{  
		ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');
	}
	if(flen>5)flen=5;	//最多取5位小数
	*dx=flen;	 		//小数点位数
	for(i=0;i<flen;i++)	//得到小数部分数据
	{  
		fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');
	} 
	res=ires*NMEA_Pow(10,flen)+fres;
	if(mask&0X02)res=-res;		   
	return res;
}	  

/**
  * @brief  
  * param
  * @retval None
  */
void NMEA_GNVTG_Analysis(nmea_msg *gpsx,uint8_t *buf)
{
	uint8_t *p1,dx;			 
	uint8_t posx;    
	p1=(uint8_t*)strstr((const char *)buf,"$GNVTG");							 
	posx=NMEA_Comma_Pos(p1,7);								//得到地面速率
	if(posx!=0XFF)
	{
		gpsx->speed=NMEA_Str2num(p1+posx,&dx);
		if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx);	 	 		//确保扩大1000倍
	}
}  
/**
  * @brief  
  * param
  * @retval None
  */
void NMEA_GNRMC_Analysis(nmea_msg *gpsx,uint8_t *buf)
{
	uint8_t *p1,dx;			 
	uint8_t posx;     
	uint32_t temp;	   
	float rs;  
	p1=(uint8_t*)strstr((const char *)buf,"$GNRMC");//"$GNRMC",经常有&和GNRMC分开的情况,故只判断GPRMC.
	posx=NMEA_Comma_Pos(p1,1);								//得到UTC时间
	if(posx!=0XFF)
	{
		temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);	 	//得到UTC时间,去掉ms
		gpsx->utc.hour=temp/10000;
		gpsx->utc.min=(temp/100)%100;
		gpsx->utc.sec=temp%100;	 	 
	}	
	
	posx=NMEA_Comma_Pos(p1,2);								//得到定位状态
	if(posx!=0XFF)
	{
		gpsx->gpssta = *(p1+posx);
		if(gpsx->gpssta=='A')//定位有效
		{
			
		}
		else//定位无效
		{
			gpsx->altitude = 0;
			gpsx->ewhemi = 0;
			gpsx->latitude = 0;
			gpsx->longitude = 0;
			gpsx->nshemi = 0;
			gpsx->speed = 0;
			return;
		}
	}
	
	posx=NMEA_Comma_Pos(p1,3);								//得到纬度
	if(posx!=0XFF)
	{
		temp=NMEA_Str2num(p1+posx,&dx);		 	 
		gpsx->latitude=temp/NMEA_Pow(10,dx+2);	//得到°
		rs=temp%NMEA_Pow(10,dx+2);				//得到'		 
		gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° 
	}
	posx=NMEA_Comma_Pos(p1,4);								//南纬还是北纬 
	if(posx!=0XFF)gpsx->nshemi=*(p1+posx);					 
 	posx=NMEA_Comma_Pos(p1,5);								//得到经度
	if(posx!=0XFF)
	{												  
		temp=NMEA_Str2num(p1+posx,&dx);		 	 
		gpsx->longitude=temp/NMEA_Pow(10,dx+2);	//得到°
		rs=temp%NMEA_Pow(10,dx+2);				//得到'		 
		gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° 
	}
	posx=NMEA_Comma_Pos(p1,6);								//东经还是西经
	if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);		
	
	
	posx=NMEA_Comma_Pos(p1,8);								//地面航向
	if(posx!=0XFF)
	{
		temp=NMEA_Str2num(p1+posx,&dx);		 	 
		gpsx->course = temp;	
	}

	
	posx=NMEA_Comma_Pos(p1,9);								//得到UTC日期
	if(posx!=0XFF)
	{
		temp=NMEA_Str2num(p1+posx,&dx);		 				//得到UTC日期
		gpsx->utc.date=temp/10000;
		gpsx->utc.month=(temp/100)%100;
		gpsx->utc.year=2000+temp%100;	 	 
	} 
}

char * json_package(enum json_print_formate flag,UploadMesTypeDef *mes)
{
	cJSON *root = NULL;   
	char *out = NULL;

	root =cJSON_CreateObject();   /*根*/
	
	cJSON_AddNumberToObject(root, "FT", mes->FT);  //通讯网络类型
	cJSON_AddStringToObject(root, "HX", mes->HX);  //终端硬件ID
	cJSON_AddNumberToObject(root, "LO", mes->LO);  //经度
	cJSON_AddNumberToObject(root, "LA", mes->LA);  //纬度
	cJSON_AddNumberToObject(root, "SP", mes->SP);  //地速
	cJSON_AddNumberToObject(root, "HE", mes->HE);  //高度
	cJSON_AddStringToObject(root, "CO", mes->CO);  //方向
	cJSON_AddStringToObject(root, "TE", mes->TE);  //定位时间
	cJSON_AddStringToObject(root, "RT", mes->RT);  //收到消息的时间
	cJSON_AddStringToObject(root, "FN", mes->FN);  //车牌号
	cJSON_AddStringToObject(root, "RE", mes->RE);  //终端注册号

	if(JSON_OUT_FORMATE == flag)
	{
			out = cJSON_Print(root);   
	}
	else
	{
			out = cJSON_PrintUnformatted(root);/*将json形式打印成正常字符串形式*/
	}

	/*释放内存*/  
	cJSON_Delete(root);     

	return out;
}

void json_parse(char *data,IssueMesTypeDef *mes)
{
	cJSON *json=0;
	cJSON *json_item=0;
	json = cJSON_Parse(data);
	char str[30];
	if (!json)
	{
		sprintf(str,"Error fmt error\n:");
		//UART_SendStr(USART2,str);
	}
	else 
	{
		json_item = cJSON_GetObjectItem(json, "warnTip");
		if(json_item->type==cJSON_Number)
		{
			mes->warnTip = json_item->valueint;
			//sprintf(str,"warnTip:%d\n", mes->warnTip);
			//UART_SendStr(USART2,str);
		}
		
		
		json_item = cJSON_GetObjectItem(json, "msg");
		if(json_item->type==cJSON_String)
		{
			strcpy(mes->msg,json_item->valuestring);
			//sprintf(str,"msg:%s\n", mes->msg);
			//UART_SendStr(USART2,str);
		}
		
		json_item = cJSON_GetObjectItem(json, "lng");
		if(json_item->type==cJSON_Number)
		{
			mes->lng = json_item->valuedouble;
			//sprintf(str,"lng:%f\n", mes->lng);
			//UART_SendStr(USART2,str);
		}
		
		json_item = cJSON_GetObjectItem(json, "warnType");
		if(json_item->type==cJSON_Number)
		{
			mes->warnTip = json_item->valueint;
			//sprintf(str,"warnType:%d\n", mes->warnTip);
			//UART_SendStr(USART2,str);
		}
		
		json_item = cJSON_GetObjectItem(json, "runway");
		if(json_item->type==cJSON_String)
		{
			strcpy(mes->runway,json_item->valuestring);
			//sprintf(str,"runway:%s\n", mes->runway);
			//UART_SendStr(USART2,str);
		}
		
		json_item = cJSON_GetObjectItem(json, "terminalId");
		if(json_item->type==cJSON_String)
		{
			strcpy(mes->terminalId,json_item->valuestring);
			//sprintf(str,"terminalId:%s\n", mes->terminalId);
			//UART_SendStr(USART2,str);
		}
		
		
		json_item = cJSON_GetObjectItem(json, "lat");
		if(json_item->type==cJSON_Number)
		{
			mes->lat = json_item->valuedouble;
			//sprintf(str,"lat:%f\n",mes->lat);
			//UART_SendStr(USART2,str);
		}
		
		json_item = cJSON_GetObjectItem(json, "height");
		if(json_item->type==cJSON_Number)
		{
			mes->height = json_item->valuedouble;
			//sprintf(str,"height:%f\n", json_item->valuedouble);
			//UART_SendStr(USART2,str);
		}
	}
	cJSON_Delete(json);
}

int set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop)

{

	struct termios newtio,oldtio;

	if(tcgetattr(fd,&oldtio)!=0)

	{

		perror("SetupSerial 1");

		return -1;

	}

	bzero(&newtio,sizeof(newtio));

	newtio.c_cflag |= CLOCAL|CREAD;

	newtio.c_cflag&=~CSIZE;

	switch(nBits)

	{

		case 7:

			newtio.c_cflag|=CS7;

			break;

		case 8:

			newtio.c_cflag|=CS8;

			break;

	}

	switch(nEvent)

	{

		case 'O':

			newtio.c_cflag|=PARENB;

			newtio.c_cflag|=PARODD;

			newtio.c_cflag|=(INPCK|ISTRIP);

			break;

		case 'E':

			newtio.c_cflag|=(INPCK|ISTRIP);;

			newtio.c_cflag|=PARENB;

			newtio.c_cflag&=~PARODD;

			break;

		case 'N':

			newtio.c_cflag&=~PARENB;

			break;



	}

	switch(nSpeed)

	{

		case 9600:

			cfsetispeed(&newtio,B9600);

			cfsetospeed(&newtio,B9600);

			break;

		case 115200:

			cfsetispeed(&newtio,B115200);

			cfsetospeed(&newtio,B115200);

			break;

		default:

			break;

	}

	if(nStop==1)

	{

		newtio.c_cflag&=~CSTOPB;

	}

	else if(nStop==2)

	{

		newtio.c_cflag|=CSTOPB;

	}

	newtio.c_cc[VTIME] = 0;

	newtio.c_cc[VMIN] = 0;

	tcflush(fd,TCIFLUSH);

	if((tcsetattr(fd,TCSANOW,&newtio))!=0)

	{

		perror("com set error");

		return -1;

	}

	printf("set done!\n\r");

	return 0;

}





int uart_recv(int fd,char *rev_buf,int data_len)

{

	int len,fs_sel;

	fd_set fs_read;



	struct timeval tv_timeout;



	FD_ZERO(&fs_read);

	FD_SET(fd,&fs_read);



	tv_timeout.tv_sec = 5;

	tv_timeout.tv_usec = 0;



	fs_sel = select(fd+1,&fs_read,NULL,NULL,&tv_timeout);

	if(fs_sel)

	{

		len = read(fd,rev_buf,data_len);

		printf("len = %d,fs_sel = %d\n",len,fs_sel);

		return len;

	}

	else

	{

		return 0;

	}

	

}